#include "znx_proc.h"
#include "znx_listener.h"
#include "znx_worker_proc.h"
#include "znx_tcp_proc.h"
#include "znx_openssl.h"
#include "znx_session_pool.h"
#include "comm/znx_module.h"
#include "conf/znx_core_conf.h"
#include "conf/znx_http_conf.h"
// #include "conf/znx_http_site_mgr.h"


volatile znx_bool_t proc_exit = ZNX_FALSE;
znx_atomic_int64_t  server_conns = 0;
znx_atomic_int64_t  client_conns = 0;
znx_atomic_int64_t  pending_tasks = 0;


void
znx_proc_init()
{
    znx_ssl_init();
    znx_g_listeners_init();
    znx_modules_init();
    // znx_http_site_mgr_init();
    znx_worker_processor_init();
}


void
znx_proc_start()
{
    znx_mem_init((size_t)g_core_conf->g_mem_freelists_level);
    znx_4kaligned_mem_init((size_t)g_core_conf->g_aligned_mem_freelists_level);
    znx_t_session_pool_init((size_t)g_core_conf->thread_session_pool_size);
    znx_ssl_session_cache_init(g_core_conf->ssl_session_cache_size);

    znx_tcp_accepter_init(
        (int)g_core_conf->tcp_accepter_threads,
        (int)g_core_conf->multiple_accept_num);

    znx_worker_processor_add_init_hook(znx_modules_worker_init_handle);
    znx_worker_processor_add_proc_exit_hook(znx_modules_worker_proc_exit_handle);
    znx_worker_processor_add_quit_hook(znx_modules_worker_exit_handle);

    znx_worker_processor_start(
        (int)g_core_conf->worker_threads,
        (size_t)g_core_conf->worker_mem_freelist_level,
        (size_t)g_core_conf->worker_aligned_mem_freelists_level);
    znx_tcp_accepter_start((int)g_core_conf->tcp_accepter_threads);
}


void
znx_proc_shutdown()
{
    proc_exit = ZNX_TRUE;

    znx_g_listeners_close();

    znx_tcp_accepter_stop();

    znx_worker_process_quit();

    for ( ;; ) {
        if (znx_atomic_int64_load(&server_conns) == 0 &&
            znx_atomic_int64_load(&client_conns) == 0 &&
            znx_atomic_int64_load(&pending_tasks) == 0)
        {
            break;
        }

        usleep(10000);
    }

    znx_worker_processor_stop();

    znx_modules_main_exit_exec();

    znx_ssl_session_cache_destroy();
    // znx_http_site_mgr_destroy();
    znx_http_main_destroy();
    znx_core_conf_destroy();

    znx_mem_clean();
    znx_4kaligned_mem_clean();

#if (ZNX_DUMP_MEM_STATUS)
    // 内存池未初始化之前申请的内存可能释放到内存池上, 导致used状态变为负数.
    // 某些全局数据结构在程序终止时没有回收对应的内存空间.
    char buf[4096];
    znx_mem_status_report(buf, 4096);
    ZNX_DEF_LOG_DEBUG(NULL, "mem_status:\n%s", buf);
    znx_4kaligned_mem_status_report(buf, 4096);
    ZNX_DEF_LOG_DEBUG(NULL, "4kaligned_mem_status:\n%s", buf);
#endif

    znx_def_log_stop();
}